package com.tron.sync.service;

import com.tron.sync.entities.SyndaOrgDoc;
import com.tron.sync.entities.SyndaUserDoc;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * synda用户，机构全文检索操作类
 */
@Service
public class ElkService {

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    public Integer saveUser(List<SyndaUserDoc> syndaUserDocs) {
        final Iterable<SyndaUserDoc> save = elasticsearchRestTemplate.save(syndaUserDocs);
        final Iterator<SyndaUserDoc> iterator = save.iterator();
        Integer total = 0;
        while (iterator.hasNext()) {
            total++;
            iterator.next();
        }
        return total;
    }

    public Integer saveOrg(List<SyndaOrgDoc> syndaOrgDocs) {
        final Iterable<SyndaOrgDoc> save = elasticsearchRestTemplate.save(syndaOrgDocs);
        final Iterator<SyndaOrgDoc> iterator = save.iterator();
        Integer total = 0;
        while (iterator.hasNext()) {
            total++;
            iterator.next();
        }
        return total;
    }

    public void cleanUser() {
        final NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        final NativeSearchQuery query = nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery()).build();
        elasticsearchRestTemplate.delete(query,SyndaUserDoc.class,IndexCoordinates.of("syndauserdoc"));
    }

    public void cleanOrg() {
        final NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        final NativeSearchQuery query = nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery()).build();
        elasticsearchRestTemplate.delete(query,SyndaOrgDoc.class,IndexCoordinates.of("syndaorgdoc"));
    }

    public Object getMapping() {
        final IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(SyndaUserDoc.class);
        final Map<String, Object> userMapping = indexOperations.getMapping();
        final IndexOperations indexOperations1 = elasticsearchRestTemplate.indexOps(SyndaOrgDoc.class);
        final Map<String, Object> orgMapping = indexOperations1.getMapping();
        final HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("userMapping", userMapping);
        hashMap.put("orgMapping", orgMapping);
        return hashMap;
    }

    public Object deleteIndex() {
        final IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(SyndaOrgDoc.class);
        final boolean delete = indexOperations.delete();
        final IndexOperations indexOperations1 = elasticsearchRestTemplate.indexOps(SyndaUserDoc.class);
        final boolean delete1 = indexOperations1.delete();
        if (delete && delete1) {
            return true;
        }
        return false;
    }

    public HashMap<String, Long> countUser(String orgId) {
        final HashMap<String, Long> hashMap = new HashMap<>();
        final NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.regexpQuery("path",".*"+orgId+".*"));
        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 1));
        final NativeSearchQuery build = nativeSearchQueryBuilder.addAggregation(
                AggregationBuilders.terms("userStatus").field("status")
        ).build();
        final SearchHits<SyndaUserDoc> search = elasticsearchRestTemplate.search(build, SyndaUserDoc.class, IndexCoordinates.of("syndauserdoc"));
        final Aggregations aggregations = search.getAggregations();
        final Map<String, Aggregation> asMap = aggregations.getAsMap();
        final ParsedStringTerms aggregation = (ParsedStringTerms) asMap.get("userStatus");
        final List<? extends Terms.Bucket> buckets = aggregation.getBuckets();
        buckets.forEach(b->{
            hashMap.put((String) b.getKey(),b.getDocCount());
        });
        // inactive=27363, deleted=423, locked=3, actived=243
        long inactive = hashMap.get("inactive") == null ? 0L : hashMap.get("inactive");
        long deleted = hashMap.get("deleted") == null ? 0L : hashMap.get("deleted");
        long locked = hashMap.get("locked") == null ? 0L : hashMap.get("locked");
        long actived = hashMap.get("actived") == null ? 0L : hashMap.get("actived");
        long total = inactive + deleted + locked + actived;
        final HashMap<String, Long> resultMap = new HashMap<>();
        resultMap.put("inactive",inactive );
        resultMap.put("deleted", deleted);
        resultMap.put("locked", locked);
        resultMap.put("actived", actived);
        resultMap.put("total",total );
        return resultMap;
    }

    public HashMap<String, Long> countOrg(String orgId) {
        final HashMap<String, Long> hashMap = new HashMap<>();
        final NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.regexpQuery("path",".*"+orgId+".*"));
        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 1));
        final NativeSearchQuery build = nativeSearchQueryBuilder.addAggregation(
                AggregationBuilders.terms("attribute").field("attribute")
        ).build();
        final SearchHits<SyndaOrgDoc> search = elasticsearchRestTemplate.search(build, SyndaOrgDoc.class, IndexCoordinates.of("syndaorgdoc"));
        final Aggregations aggregations = search.getAggregations();
        final Map<String, Aggregation> asMap = aggregations.getAsMap();
        final ParsedStringTerms aggregation = (ParsedStringTerms) asMap.get("attribute");
        final List<? extends Terms.Bucket> buckets = aggregation.getBuckets();
        buckets.forEach(b->{
            hashMap.put((String) b.getKey(),b.getDocCount());
        });
        long org1 = hashMap.get("1") == null ? 0L : hashMap.get("1");
        long org2 = hashMap.get("2") == null ? 0L : hashMap.get("2");
        final HashMap<String, Long> resultMap = new HashMap<>();
        resultMap.put("org1", org1);
        resultMap.put("org2", org2);
        return resultMap;
    }

    public ArrayList<Map<String, Object>> countOrgUser(String orgId) {
        // 获取一级机构
        final NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("orgPid", orgId));
        final SearchHits<SyndaOrgDoc> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), SyndaOrgDoc.class);
        final ArrayList<Map<String, Object>> maps = new ArrayList<>();
        final List<SearchHit<SyndaOrgDoc>> searchHits = search.getSearchHits();
        searchHits.forEach(i->{
            HashMap<String, Object> hashMap = new HashMap<>();
            final SyndaOrgDoc content = i.getContent();
            hashMap.put("id", content.getId());
            hashMap.put("name",content.getName());
            final HashMap<String, Long> countUser = countUser(content.getId());
            hashMap.put("data", countUser.get("total"));
            maps.add(hashMap);
        });
        return maps;
    }

    public ArrayList<SyndaUserDoc> getUserByPinYin(String orgId,String condition) {
        final ArrayList<SyndaUserDoc> syndaUserDocs = new ArrayList<>();
        final NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.boolQuery()
                .should(QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("pinyin",condition))
                        .must(QueryBuilders.regexpQuery("path",".*"+orgId+".*"))
                )
                .should(QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("name", condition).minimumShouldMatch("100%"))
                        .must(QueryBuilders.regexpQuery("path",".*"+orgId+".*"))
                ).minimumShouldMatch(1)
        );
        final NativeSearchQuery query = nativeSearchQueryBuilder.build();
        final SearchHits<SyndaUserDoc> search = elasticsearchRestTemplate.search(query, SyndaUserDoc.class);
        search.getSearchHits().stream().forEach(e->{
            final SyndaUserDoc content = e.getContent();
            syndaUserDocs.add(content);
        });
        return syndaUserDocs;
    }


    public List<SyndaOrgDoc> getOrgByPinYin(String orgId,String condition) {
        final NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.boolQuery()
                .should(QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("orgAlias", condition))
                        .must(QueryBuilders.regexpQuery("path", ".*" + orgId + ".*"))
                )
                .should(QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("name", condition).minimumShouldMatch("100%"))
                        .must(QueryBuilders.regexpQuery("path",".*"+orgId+".*"))
                ).minimumShouldMatch(1)
        );
        final NativeSearchQuery query = nativeSearchQueryBuilder.build();
        final SearchHits<SyndaOrgDoc> search = elasticsearchRestTemplate.search(query, SyndaOrgDoc.class);
        final List<SyndaOrgDoc> orgDocs = search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
        return orgDocs;
    }


}
